<?php

/**
 * SigmaCMS - Content Management System
 *
 * Copyright (C) 2008 Pavol Biely
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 * @package    SigmaCMS
 * @author     Pavol Biely <pavolbiely@gmail.com>
 * @copyright  2008 Pavol Biely
 * @license    http://www.gnu.org/licenses/gpl.txt   GNU General Public License
 * @link       http://pabi3.com/
 * @since      0.1.0
 */

final class Admin_Skins
{
	/**
	 * Initialization
	 *
	 * @return void
	 */
	public function initialize()
	{
		Admin::header(_ADMIN_SKINS);

		echo "<h1>"._ADMIN_SKINS."</h1>\n";

		// path to directories
		$path = dirname(__FILE__).'/../../'.cfg::DIR_SKINS;

		// load directory list
		$skinDirs = scandir($path);

		// remove symlinks
		array_splice($skinDirs, 0, 2);

		// does directories exist?
		if (count($skinDirs) > 0) {
			echo "<table>\n";

			echo "<colgroup>\n";
			echo "<col width='20%' align='center' />\n";
			echo "<col width='60%' align='left' />\n";
			echo "<col width='20%' align='center' />\n";
			echo "</colgroup>\n";

			echo "<thead>\n";
			echo "<tr>\n";
			echo "<th>"._ADMIN_SKINS_DIR."</th>\n";
			echo "<th>"._ADMIN_SKINS."</th>\n";
			echo "<th>"._ADMIN_ACTIONS."</th>\n";
			echo "</tr>\n";
			echo "</thead>\n";

			// print skins
			echo "<tbody>\n";
			foreach ($skinDirs as $key => $skinDir) {
				// skip invalid skin names
				if (!preg_match("/^(\w+)$/", $skinDir)) {
					continue;
				}

				echo "<tr>\n";
				echo "<td>\n";
				if ($skinDir.'/' == cfg::get('skin')) {
					echo "<strong class='green'>".$skinDir."</strong>\n";
				} else {
					echo $skinDir;
				}
				echo "</td>\n";
				echo "<td>\n";

				// skins and directories
				$skins = glob($path.$skinDir.'/*'.Main::SKIN_SUFFIX);

				// does skins exist?
				if (count($skins) > 0) {
					// note about a new skin
					$newSkins = false;

					// list of skins
					foreach ($skins as $_key => $skin) {
						// extract a skin name
						preg_match('/([a-z0-9-]+)\\'.Main::SKIN_SUFFIX.'$/',$skin,$matches);

						// skin name
						$skinName = $matches[1];

						// does the skin exist in the database?
						if (false === db::fQuery("SELECT `id` FROM ".db::prefix('skins')." WHERE `id`='".db::escape($skinName)."' AND `skin`='".db::escape($skinDir)."'")) {
							// insert the skin to the database
							db::query("INSERT INTO ".db::prefix('skins')."(`id`,`ctype`,`skin`) VALUES('".db::escape($skinName)."','application/xhtml+xml','".db::escape($skinDir)."')");

							// log action
							Actionlog::add(sprintf(_LOG_ADMIN_SKIN_ADD,$skinName,$skinDir));

							// event after adding a new skin
							Admin::addEvent('skinAdd',$skinName,$skinDir);

							// note about a new skin
							$newSkins = true;
						}

						// print a skin
						echo "<div class='skin'>\n";
						echo "<div class='float-left'>$skinName</div>\n";
						echo "<div class='float-right'>\n";
						echo "<a href='index.php?action=skins&amp;page=edit&amp;skin=$skinName&amp;dir=$skinDir'>".Admin::image('edit',_ADMIN_SKINS_EDIT)."</a>\n";
						echo "<a href='index.php?action=skins&amp;page=delete&amp;skin=$skinName&amp;dir=$skinDir'>".Admin::image('delete',_ADMIN_SKINS_DELETE)."</a>\n";
						echo "</div>\n";
						echo "<div class='clear-both'></div>\n";
						echo "</div>\n";
					}

					// "silent" installation of new skins
					if ($newSkins) {
						echo "<div class='box'>\n";
						echo sprintf(_ADMIN_SKINS_NEW_INSTALLED,'/'.cfg::DIR_SKINS.$skinDir);
						echo "</div>\n";
					}
				} else if (count($skinDirs) == 1) {
					echo "<p class='red'>".sprintf(_ADMIN_SKINS_EMPTY_ALONE,"index")."</p>\n";
				} else {
					echo "<p>"._ADMIN_SKINS_EMPTY."</p>\n";
				}
				echo "</td>\n";

				echo "<td>\n";
				echo "<a href='index.php?action=skins&amp;page=add&amp;dir=$skinDir'>".Admin::image('add',_ADMIN_SKINS_ADD)."</a>\n";
				echo "</td>\n";

				echo "</tr>\n";
			}
			echo "</tbody>\n";

			echo "</table>\n";
		} else {
			echo "<p class='red'>"._ADMIN_SKINS_EMPTY_DIRS."</p>\n";
		}

		Admin::footer();
	}

	/**
	 * Set CHMOD
	 *
	 * @param string $filename
	 * @param integer $mode
	 * @return void
	 */
	private function setCHMOD($filename, $mode = 0777)
	{
		$old = umask(0);
		chmod($filename, $mode);
		umask($old);
	}

	/**
	 * Add a new skin
	 *
	 * @return void
	 */
	public function page_add()
	{
		// directory must be defined
		if (isset($_GET['dir'])) {
			$dir = _hsc(_get('dir'));
		} else {
			Admin::redirect('index.php?action=skins');
		}

		Admin::header(_ADMIN_SKINS_ADD);

		echo "<h1>"._ADMIN_SKINS_ADD."</h1>\n";

		// error reports
		$error = array();
		if (isset($_POST['submit'])) {
			// ID/URL
			$id = strtolower(_post('id'));
			if (!preg_match('/^([a-z0-9-]+)$/',$id)) {
				$error[] = _ADMIN_SKINS_ERROR_ID;
			} else if (false !== db::fQuery("SELECT * FROM ".db::prefix('skins')." WHERE `id`='".db::escape($id)."' AND `skin`='".db::escape($dir)."'")) {
				$error[] = _ADMIN_SKINS_ERROR_ID_EXISTS;
			}

			// MIME type
			$ctype = _post('ctype');
			if (strlen(trim($ctype)) == 0) {
				$error[] = _ADMIN_SKINS_ERROR_CTYPE;
			}

			// skin content
			$content = _post('content');

			// no error occurred?
			if (count($error) == 0) {
				// path to skin
				$skinPath = dirname(__FILE__).'/../../'.cfg::DIR_SKINS.Media::clearPath($dir).'/';

				// save a new content of a skin to the file
				if (@file_put_contents($skinPath.$id.Main::SKIN_SUFFIX, $content)) {
					// set access rights
					$this->setCHMOD($skinPath.$id.Main::SKIN_SUFFIX);

					// insert a new skin to the database
					$sql = db::query("INSERT INTO ".db::prefix('skins')."(`id`,`ctype`,`skin`) VALUES('".db::escape($id)."','".db::escape($ctype)."','".db::escape($dir)."')");

					// success?
					if ($sql) {
						// log action
						Actionlog::add(sprintf(_LOG_ADMIN_SKIN_ADD, $id, $dir));

						// event after adding a new skin
						Admin::addEvent('skinAdd', $id, $dir);

						// redirect
						Admin::redirect('index.php?action=skins');
					} else {
						// remove a skin file
						@unlink($skinPath.$id.Main::SKIN_SUFFIX);
						echo "<p class='red'>"._ADMIN_SKINS_ERROR_SQL."</p>\n";
					}
				} else {
					echo "<p class='red'>"._ADMIN_SKINS_ERROR_SAVE."</p>\n";
				}
			} else {
				// print error messages
				foreach ($error as $key => $value) {
					echo "<p class='red'>$value</p>\n";
				}
			}
		}

		echo "<form action='index.php?action=skins&amp;page=add&amp;dir=$dir' method='post'>\n";
		echo "<fieldset>\n";

		echo "<label for='id'>"._ADMIN_SKINS_ID." <small>[a-z0-9-]+</small></label>\n";
		echo "<input id='id' name='id' type='text' value='"._hsc(_post('id'))."' />\n";

		echo "<label for='ctype'>"._ADMIN_SKINS_CTYPE."</label>\n";
		echo "<input id='ctype' name='ctype' type='text' value='".(_post('ctype') ? _hsc(_post('ctype')) : 'application/xhtml+xml')."' />\n";

		echo "<label for='content'>"._ADMIN_SKINS_CONTENT."</label>\n";

		Admin::addEvent('preSkinTextarea','content','content',_post('content'));
		echo "<textarea id='content' name='content' cols='50' rows='20'>"._hsc(_post('content'))."</textarea>\n";
		Admin::addEvent('posSkinTextarea','content','content',_post('content'));

		echo "<p class='center'>\n";
		echo "<input name='submit' type='submit' value='"._ADMIN_ADD."' />\n";
		echo "</p>\n";

		echo "</fieldset>\n";
		echo "</form>\n";

		Admin::footer();
	}

	/**
	 * Edit a skin
	 *
	 * @return void
	 */
	public function page_edit()
	{
		// the skin and the directory must be defined
		if (isset($_GET['skin'], $_GET['dir']) && preg_match('/^([a-z0-9-]+)$/', $_GET['skin'])) {
			$skin = _get('skin');
			$dir  = _hsc(Media::clearPath(_get('dir')));
		} else {
			Admin::redirect('index.php?action=skins');
		}

		Admin::header(_ADMIN_SKINS_EDIT);

		echo "<h1>"._ADMIN_SKINS_EDIT."</h1>\n";

		// error reports
		$error = array();
		if (isset($_POST['submit'])) {
			// ID/URL
			$id = strtolower(_post('id'));
			if (!preg_match('/^([a-z0-9-]+)$/',$id)) {
				$error[] = _ADMIN_SKINS_ERROR_ID;
			}

			// MIME type
			$ctype = _post('ctype');
			if (strlen(trim($ctype)) == 0) {
				$error[] = _ADMIN_SKINS_ERROR_CTYPE;
			}

			// skin content
			$content = _post('content');

			// no error occurred?
			if (count($error) == 0) {
				// update the skin in the database
				$sql = db::query("UPDATE ".db::prefix('skins')." SET ".
				" `id`='".db::escape($id)."',".
				" `ctype`='".db::escape($ctype)."'".
				" WHERE `id`='".db::escape($skin)."' AND `skin`='".db::escape($dir)."'");

				// success?
				if ($sql) {
					// path to the skin
					$skinPath = dirname(__FILE__).'/../../'.cfg::DIR_SKINS.Media::clearPath($dir).'/';

					// delete the old file of the skin, if it was renamed
					if ($skin != $id) {
						// set access rights
						$this->setCHMOD($skinPath.$skin.Main::SKIN_SUFFIX);
						@unlink($skinPath.$skin.Main::SKIN_SUFFIX);
					}

					// save a new content to the new file
					if (@file_put_contents($skinPath.$id.Main::SKIN_SUFFIX,$content)) {
						// set access rights
						$this->setCHMOD($skinPath.$id.Main::SKIN_SUFFIX);

						// log action
						Actionlog::add(sprintf(_LOG_ADMIN_SKIN_EDIT,$id,$dir));

						// event after editing a skin
						Admin::addEvent('skinEdit', $id, $dir);

						// redirect
						Admin::redirect('index.php?action=skins');
					} else {
						echo "<p class='red'>"._ADMIN_SKINS_ERROR_SAVE."</p>\n";
					}
				} else {
					echo "<p class='red'>"._ADMIN_SKINS_ERROR_SQL."</p>\n";
				}
			} else {
				// print error messages
				foreach ($error as $key => $value) {
					echo "<p class='red'>$value</p>\n";
				}
			}
		}

		// path to skins
		$path = dirname(__FILE__).'/../../'.cfg::DIR_SKINS.Media::clearPath($dir).'/';

		// skin content
		$skinContent = NULL;

		// does the skin exist?
		if (file_exists($path.$skin.Main::SKIN_SUFFIX)) {
			// load the skin content
			$skinContent = file_get_contents($path.$skin.Main::SKIN_SUFFIX);
		} else {
			echo "<p class='red'>"._ADMIN_SKINS_NOT_FOUND."</p>\n";
			Admin::footer();
			exit;
		}

		// check if the skin exist in the database
		$sql = db::query("SELECT `id`,`ctype`,`skin` FROM ".db::prefix('skins')." WHERE `id`='".db::escape($skin)."' AND `skin`='".db::escape($dir)."' LIMIT 1");
		$row = db::fetchObject($sql);
		if (db::numRows($sql) == 1) {
			echo "<form action='index.php?action=skins&amp;page=edit&amp;skin=$skin&amp;dir=$dir' method='post'>\n";
			echo "<fieldset>\n";

			echo "<label for='id'>"._ADMIN_SKINS_ID." <small>[a-z0-9-]+</small></label>\n";
			echo "<input id='id' name='id' type='text' value='"._hsc($row->id)."' />\n";

			echo "<label for='ctype'>"._ADMIN_SKINS_CTYPE."</label>\n";
			echo "<input id='ctype' name='ctype' type='text' value='"._hsc($row->ctype)."' />\n";

			echo "<label for='content'>"._ADMIN_SKINS_CONTENT."</label>\n";

			Admin::addEvent('preSkinTextarea','content','content',$skinContent);
			echo "<textarea id='content' name='content' cols='50' rows='20'>"._hsc($skinContent)."</textarea>\n";
			Admin::addEvent('posSkinTextarea','content','content',$skinContent);

			echo "<p class='center'>\n";
			echo "<input name='submit' type='submit' value='"._ADMIN_EDIT."' />\n";
			echo "</p>\n";

			echo "</fieldset>\n";
			echo "</form>\n";
		}
		db::free($sql);

		Admin::footer();
	}

	/**
	 * Delete a skin
	 *
	 * @return void
	 */
	public function page_delete()
	{
		// the skin and the directory must be defined
		if (isset($_GET['skin'],$_GET['dir']) && preg_match('/^([a-z0-9-]+)$/',$_GET['skin'])) {
			$skin = _get('skin');
			$dir  = _hsc(Media::clearPath(_get('dir')));
		} else {
			Admin::redirect('index.php?action=skins');
		}

		Admin::header(_ADMIN_SKINS_DELETE);

		// confirmed?
		if (_get('sure') == 1) {
			// path to skins
			$path = dirname(__FILE__).'/../../'.cfg::DIR_SKINS;

			// set access rights
			$this->setCHMOD($path.Media::clearPath($dir).'/'.Media::clearPath($skin).Main::SKIN_SUFFIX);

			// delete the skin file
			@unlink($path.Media::clearPath($dir).'/'.Media::clearPath($skin).Main::SKIN_SUFFIX);

			// delete the skin from the database
			db::query("DELETE FROM ".db::prefix('skins')." WHERE `id`='".db::escape($skin)."' AND `skin`='".db::escape($dir)."'");

			// log action
			Actionlog::add(sprintf(_LOG_ADMIN_SKIN_DELETE,$skin,$dir));

			// event after deleting the skin
			Admin::addEvent('skinDelete',$skin,$dir);

			// redirect
			Admin::redirect('index.php?action=skins');
		} else {
			// confirmation form
			Admin::confirm('index.php?action=skins&page=delete&skin='.$skin.'&dir='.$dir.'&sure=1');
		}

		Admin::footer();
	}
}
